package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
)

func main() {

	/**
	1、从控制台获取爬虫的 页数（start- end）
	2、http请求获取数据内容
	3、将内容写入文件
	*/
	var start, end int64
	fmt.Printf("清输入爬虫的起始页数（page>=1）\n")
	fmt.Scan(&start)
	fmt.Printf("清输入爬虫的结束页数\n")
	fmt.Scan(&end)
	fmt.Printf("从 %d 开始进行爬虫 %d 结束\n", start, end)

	pagecount := make(chan int)

	for i := int(start); i < int(end); i++ {
		url := "https://tieba.baidu.com/f?kw=golang&ie=utf-8&pn=" + strconv.Itoa(i*50)
		/**
		######
		以下函数 可以选用3中方式之一，

		三蛋 ：我认为这个主要原因是由于 之前的 匿名函数 在形参中，只有类型，没有形参的对应的名称导致的，
		对于是否封装一个模块来执行、还是不封住分步骤执行，与这个关系不大，很多程序员对着 没有太深的理解，
		你有空看下，
		*/
		/*
				//1、可以使用 匿名函数进行 执行 （注意匿名函数之前只有类型 没有形参,）
				正确的写法
				go func(j int, u string, c chan int) {
					fmt.Printf("index=%d \n", j)
					doWork(j, u, c)
				}(i, url, pagecount)
				采坑的写法
				go func( int, string, chan int) {
						fmt.Printf("index=%d \n", i)
						doWork(i, url, pagecount)
				}(i, url, pagecount)
				//2、可以使用 封装的函数执行（注意匿名函数之前只有类型 没有形参,）
				正确的写法
				go func(j int, u string, c chan int) {
					fmt.Printf("处理 %dpage 中\n", j)
					content, err := handlerUrl(j, u)
					if err != nil {
						fmt.Printf("err %v\n", err)
					}
					filename := "./" + strconv.Itoa(j) + ".html"
					writerFile(filename, content)
					fmt.Printf("存放成成功=%d", j)
					pagecount <- j
				}(i, url, pagecount)
				采坑的写法
				go func( int, string, chan int) {
					fmt.Printf("处理 %dpage 中\n", i)
					content, err := handlerUrl(i, url)
					if err != nil {
						fmt.Printf("err %v\n", err)
					}
					filename := "./" + strconv.Itoa(i) + ".html"
					writerFile(filename, content)
					fmt.Printf("存放成成功=%d", i)
					pagecount <- i
			    }(i, url, pagecount)
		*/
		//3、直接使用 原来的参数执行
		go doWork(i, url, pagecount)
	}

	for v := range pagecount {
		fmt.Printf("第%d 页面爬虫完毕\n", v)
	}

}

//获取的内容的 存入文件的调用
func doWork(i int, url string, pagecount chan int) {
	content, err := handlerUrl(i, url)
	if err != nil {
		fmt.Printf("err %v", err)
	}
	filename := "./" + strconv.Itoa(i) + ".html"
	writerFile(filename, content)
	fmt.Printf("存放成成功=%d \n", i)
	pagecount <- i
}

//通过url 获取url 对应的内容
func handlerUrl(i int, url string) (content string, err error) {
	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("http get err=%v \n", err)
		return "", err
	}
	defer resp.Body.Close()
	bytes, err := ioutil.ReadAll(resp.Body)
	return string(bytes), nil
}

//将获取的内容的 写入文件中
func writerFile(fileName string, content string) {
	//file, err := os.Create("./" + strconv.Itoa(i) + ".html")
	file, err := os.Create(fileName)
	if err != nil {
		fmt.Printf("create file err=%s \n", err)
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	defer writer.Flush()
	fmt.Fprintln(writer, content)
}
